2.3.6 Audio Reproduction Samples

The following code demonstrates how to play a MIDI sequence in your game. This code is also available in the \N64Manuals\pc\allman\samples\Sequence directory of this CD.

Another audio sample on the CD demonstrates how to play sound effects. It is located in the \N64Manuals\pc\allman\samples\Effect subdirectory.

Note that all the os and al functions in the following code are included in the library. You can look them up in the N64 Function Reference Manual for more information. All other functions are defined for this sample only; they are not part of the os or al libraries.

Illustration

Sequence Reproduction Sample Code

/*----------------

 The main process

------------------*/

void mainproc(void* arg)

{

/* Initialize each type */

InitMain( );



/* The main loop */

while(1){

switch(main_no){

case GM_MAIN:

main_no = main00(&sched);

break;

}

}

}



/*-------------------

Initialize each type

---------------------*/

void InitMain(void)

{

/* Initialize the audio player */

auAudioInit( );



/* Initialize the sequence player */

auSeqPlayerInit(_midibankSegmentRomStart,

_midibankSegmentRomEnd,

_seqSegmentRomStart,

_seqSegmentRomEnd,

_miditableSegmentRomStart);



/* Create the scheduler thread */

nnScCreateScheduler(&sched, OS_VI_NTSC_LAN1, 1);



/* Create the audio thread */

auCreateAudioThread(&sched);



main_no = GM_MAIN;

}



/*---------------------------------------

  Allocate each buffer and initialize the

  parameter used in the audio library

-----------------------------------------*/

void auAudioInit(void)

{

/*initialize audio heap */

alHeapInit(&audio_heap, audio_heap_buf,

   AUDIO_HEAP_SIZE);



/* create command list buffer */

audio_cmdlist_ptr[0] = alHeapAlloc(&audio_heap,



   1,AUDIO_CLIST_SIZE_MAX*sizeof(Acmd));

audio_cmdlist_ptr[1] = alHeapAlloc(&audio_heap,



   1,AUDIO_CLIST_SIZE_MAX*sizeof(Acmd));



/* create task list buffer */

audio_tlist_ptr[0] = alHeapAlloc(&audio_heap,



   1, sizeof(OSTask));

audio_tlist_ptr[1] = alHeapAlloc(&audio_heap,



   1, sizeof(OSTask));



/* create audio buffer */

audio_buffer_ptr[0] = alHeapAlloc(&audio_heap,



   1,sizeof(s32)*AUDIO_BUFFER_MAX);

audio_buffer_ptr[1] = alHeapAlloc(&audio_heap,



   1,sizeof(s32)*AUDIO_BUFFER_MAX);

audio_buffer_ptr[2] = alHeapAlloc(&audio_heap,



   1,sizeof(s32)*AUDIO_BUFFER_MAX);



/* create message queue for DMA */

osCreateMesgQueue(&audioDmaMessageQ,



&audioDmaMessageBuf,1);

osCreateMesgQueue(&audioRomMessageQ,



&audioRomMessageBuf, 1);



/* Clear initialization flag of DMABuffer*/

dmaState.initialized = 0;



/* initialize audio library */

audio_config.outputRate= 

osAiSetFrequency(AUDIO_OUTPUT_RATE);

audio_config.maxVVoices =

AUDIO_VVOICE_MAX; /* max virtual voices */

audio_config.maxPVoices =

AUDIO_PVOICE_MAX;  /* max physical voices */

audio_config.maxUpdates = AUDIO_UPDATE_MAX;  

audio_config.dmaproc = &dmaNew;

/* DMA callback function */

audio_config.fxType = AL_FX_SMALLROOM;

/* effect type */

audio_config.heap = &audio_heap;

/* audio heap */

audio_config.params = 0;

/* custom effect */



/* Create the synthesizer (initialize

   the audio library) */

alInit(&audio_global, &audio_config);

}



/*---------------------------------------------

Initialize the sequence player

input

midi_start: The header ROM address of the

            bank file (.ctl)

midi_end: The end ROM address of the bank

          file (.ctl)

seqheader_start: The header ROM address of

                 the sequence file (.sbk)

seqheader_end: The end ROM address of the

               sequence file (.sbl)

midi_table_star: The header ROM address of

                 the wave table file (.tbl)

-----------------------------------------------*/

void auSeqPlayerInit(u8* midi_start, u8* midi_end,

u8* seqheader_start, u8* seqheader_end,

u8* midi_table_start) 

{

ALBank *midiBank_ptr;

u32 size;



/* create sequence data buffer */

seqplayer[0].seqdata_ptr =

alHeapAlloc(&audio_heap, 1,

   AUDIO_SEQDATA_SIZE_MAX);

seqplayer[1].seqdata_ptr =

alHeapAlloc(&audio_heap, 1,

   AUDIO_SEQDATA_SIZE_MAX);



/* initialize sequence player 0 */

seqplayer[0].seqconfig.maxVoices =

AUDIO_SEQ_VVOICE_MAX; /* max virtual voices */

seqplayer[0].seqconfig.maxEvents =

AUDIO_SEQ_EVTCOUNT_MAX; /* max inside events */

seqplayer[0].seqconfig.maxChannels = 

AUDIO_SEQ_CHANNEL_MAX; /* max MIDI channels */

seqplayer[0].seqconfig.heap = &audio_heap;

seqplayer[0].seqconfig.initOsc = 0;

seqplayer[0].seqconfig.updateOsc = 0;

seqplayer[0].seqconfig.stopOsc = 0;

seqplayer[0].seqconfig.debugFlags = 0;



#ifdef _AUDIO_COMPACTMIDI_

alCSPNew(&seqplayer[0].seqplayer,



   &seqplayer[0].seqconfig);

#else

alSeqpNew(&seqplayer[0].seqplayer,



   &seqplayer[0].seqconfig);

#endif /* _AUDIO_COMPACTMIDI_ */



/* initialize sequence player 1 */

seqplayer[1].seqconfig.maxVoices =

AUDIO_SEQ_VVOICE_MAX; /* max virtual voices */

seqplayer[1].seqconfig.maxEvents =

AUDIO_SEQ_EVTCOUNT_MAX; /* max inside events */

seqplayer[1].seqconfig.maxChannels =

AUDIO_SEQ_CHANNEL_MAX; /* max MIDI channels */

seqplayer[1].seqconfig.heap = &audio_heap;

seqplayer[1].seqconfig.initOsc = 0;

seqplayer[1].seqconfig.updateOsc = 0;

seqplayer[1].seqconfig.stopOsc = 0;

seqplayer[1].seqconfig.debugFlags = 0;



#ifdef _AUDIO_COMPACTMIDI_

alCSPNew(&seqplayer[1].seqplayer,



   &seqplayer[1].seqconfig);

#else

alSeqpNew(&seqplayer[1].seqplayer,



   &seqplayer[1].seqconfig);

#endif /* _AUDIO_COMPACTMIDI_ */



/* read seqfileheader data */

auReadSeqFileHeader((u32)seqheader_start);

alSeqFileNew(seqHeaderfile_ptr, seqheader_start);



/* read midi bank data */

size = (u32)midi_end-(u32)midi_start;

midi_buffer_ptr = alHeapAlloc(&audio_heap, 1, size);

auRomRead((u32)midi_start, midi_buffer_ptr, size);



/* Specify the instrument bank used by

   the sequencer */

alBnkfNew(midi_buffer_ptr, midi_table_start);

midiBank_ptr = midi_buffer_ptr->bankArray[0];



#ifdef _AUDIO_COMPACTMIDI_

alCSPSetBank(&seqplayer[0].seqplayer,



   midiBank_ptr);

alCSPSetBank(&seqplayer[1].seqplayer,



   midiBank_ptr);

#else

alSeqpSetBank(&seqplayer[0].seqplayer,



   midiBank_ptr);

alSeqpSetBank(&seqplayer[1].seqplayer,



   midiBank_ptr);

#endif /* _AUDIO_COMPACTMIDI_ */



}



/*-----------------------------------

Create and activate the audio thread

-------------------------------------*/

void auCreateAudioThread(NNSched *sched)

{

osCreateThread(&audioThread, AUDIO_THREAD_ID,

 audioProc, 

(void *)sched,

(audioThreadStack+AUDIO_STACKSIZE/sizeof(u64)),

AUDIO_THREAD_PRI);

osStartThread(&audioThread);

}



/*------------------------------

Main of the sequence reprodction

--------------------------------*/

int main00(NNSched* sched)

{

OSMesgQueue msgQ;

OSMesg msgbuf[MAX_MESGS];

NNScClient client;

u32 seqno;



/* create message queue for VI retrace */

osCreateMesgQueue(&msgQ, msgbuf, MAX_MESGS);



/* Set sequence O to sequence player O */

auSeqPlayerSetFile(0,2);



/* add client to shceduler */

nnScAddClient(sched, &client, &msgQ);



seqno = 0;

auSeqPlayerPlay(seqno);

while(1){

(void) osRecvMesg(&msgQ, NULL, OS_MESG_BLOCK);

/* If the sequence has stopped, repeat it */

if(auSeqPlayerState(0) == AL_STOPPED){

auSeqPlayerPlay(seqno);

}

}



/* exit label */

return MAIN_01;

}



/*---------------------------------------------

Reproduce the sequence

Input:

seqplayer_no: The sequence player number that

starts the reproduction.

If the sequence player is not in AL_STOPPED

state, return FALSE.

----------------------------------------------*/

int auSeqPlayerPlay(u32 seqplayer_no)

{

#ifndef _AUDIO_COMPACTMIDI_

s32 seqdata_len;

u32 seqno;

#endif /* _AUDIO_COMPACTMIDI_ */



#ifdef _AUDIO_DEBUG_

if(seqplayer_no > 1){

osSyncPrintf("seqplayer_no over!!\n");

return FALSE;

}

#endif /* _AUDIO_DEBUG_ */



/* check seqplayer state. */

if(seqplayer[seqplayer_no].seqplayer.state

   != AL_STOPPED){

#ifdef _AUDIO_DEBUG_

osSyncPrintf

   ("sequence player %d is playing\n",seqplayer_no);

#endif /* _AUDIO_DEBUG_ */

return FALSE;

}



#ifdef _AUDIO_COMPACTMIDI_

alCSeqNew(&seqplayer[seqplayer_no].sequence, 

seqplayer[seqplayer_no].seqdata_ptr);

alCSPSetSeq(&seqplayer[seqplayer_no].seqplayer, 

&seqplayer[seqplayer_no].sequence);

alCSPPlay(&seqplayer[seqplayer_no].seqplayer);

#else

seqno = seqplayer[seqplayer_no].seqno;

seqdata_len = seqHeaderfile_ptr->seqArray[seqno].len;

alSeqNew(&seqplayer[seqplayer_no].sequence,



seqplayer[seqplayer_no].seqdata_ptr, seqdata_len);

alSeqpSetSeq(&seqplayer[seqplayer_no].seqplayer,



&seqplayer[seqplayer_no].sequence);

alSeqpPlay(&seqplayer[seqplayer_no].seqplayer);

#endif /* _AUDIO_COMPACTMIDI_ */

return TRUE;

}